home *** CD-ROM | disk | FTP | other *** search
/ Qoole for Quake / Qoole for Quake (USA) / Qoole for Quake (USA).bin / Tutorial / HTML / QUBE.ZIP / SRC / VIS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-05  |  21.2 KB  |  1,031 lines

  1. /* vis.c */
  2.  
  3. #include "vis.h"
  4. #include "curs.h"
  5.  
  6. #define    MAX_THREADS        4
  7.  
  8. int            numportals;
  9. int            portalleafs;
  10.  
  11. portal_t    *portals;
  12. leaf_t        *leafs;
  13.  
  14. int            c_portaltest, c_portalpass, c_portalcheck;
  15.  
  16.  
  17. qboolean        showgetleaf = true;
  18.  
  19. int        leafon;            /* the next leaf to be given to a thread to process */
  20.  
  21. #ifdef __alpha
  22. pthread_mutex_t    *my_mutex;
  23. #endif
  24.  
  25. byte    *vismap, *vismap_p, *vismap_end;    /* past visfile */
  26. int        originalvismapsize;
  27.  
  28. byte    *uncompressed;            /* [bitbytes*portalleafs] */
  29.  
  30. int        bitbytes;                /* (portalleafs+63)>>3 */
  31. int        bitlongs;
  32.  
  33. #ifdef __alpha
  34. int            numthreads = 4;
  35. #else
  36. int            numthreads = 1;
  37. #endif
  38.  
  39. qboolean        fastvis;
  40. qboolean        verbose;
  41. int            testlevel = 2;
  42.  
  43. FILE            *LogFile;
  44.  
  45. int            nummapbrushes = 0;
  46. int            nummiptex = 0;
  47. int            num_entities = 0;
  48.  
  49. #if 0
  50. void NormalizePlane (plane_t *dp)
  51. {
  52.     double    ax, ay, az;
  53.     
  54.     if (dp->normal[0] == -1.0)
  55.     {
  56.         dp->normal[0] = 1.0;
  57.         dp->dist = -dp->dist;
  58.         return;
  59.     }
  60.     if (dp->normal[1] == -1.0)
  61.     {
  62.         dp->normal[1] = 1.0;
  63.         dp->dist = -dp->dist;
  64.         return;
  65.     }
  66.     if (dp->normal[2] == -1.0)
  67.     {
  68.         dp->normal[2] = 1.0;
  69.         dp->dist = -dp->dist;
  70.         return;
  71.     }
  72.     
  73.     ax = fabs(dp->normal[0]);
  74.     ay = fabs(dp->normal[1]);
  75.     az = fabs(dp->normal[2]);
  76.     
  77.     if (ax >= ay && ax >= az)
  78.     {
  79.         if (dp->normal[0] < 0)
  80.         {
  81.             VectorSubtract (vec3_origin, dp->normal, dp->normal);
  82.             dp->dist = -dp->dist;
  83.         }
  84.         return;
  85.     }
  86.     
  87.     if (ay >= ax && ay >= az)
  88.     {
  89.         if (dp->normal[1] < 0)
  90.         {
  91.             VectorSubtract (vec3_origin, dp->normal, dp->normal);
  92.             dp->dist = -dp->dist;
  93.         }
  94.         return;
  95.     }
  96.     
  97.     if (dp->normal[2] < 0)
  98.     {
  99.         VectorSubtract (vec3_origin, dp->normal, dp->normal);
  100.         dp->dist = -dp->dist;
  101.     }
  102. }
  103. #endif
  104.  
  105. void PlaneFromWinding (winding_t *w, plane_t *plane)
  106. {
  107.     vec3_t        v1, v2;
  108.  
  109. /* calc plane */
  110.     VectorSubtract (w->points[2], w->points[1], v1);
  111.     VectorSubtract (w->points[0], w->points[1], v2);
  112.     CrossProduct (v2, v1, plane->normal);
  113.     VectorNormalize (plane->normal);
  114.     plane->dist = DotProduct (w->points[0], plane->normal);
  115. }
  116.  
  117. /*============================================================================= */
  118.  
  119. /*
  120. ==================
  121. NewWinding
  122. ==================
  123. */
  124. winding_t *NewWinding (int points)
  125. {
  126.     winding_t    *w;
  127.     int            size;
  128.     
  129.     if (points > MAX_POINTS_ON_WINDING)
  130.         Error ("NewWinding: %i points", points);
  131.     
  132.     size = (int)((winding_t *)0)->points[points];
  133.     w = malloc (size);
  134.     memset (w, 0, size);
  135.     
  136.     return w;
  137. }
  138.  
  139.  
  140. void FreeWinding (winding_t *w)
  141. {
  142.     if (!w->original)
  143.         free (w);
  144. }
  145.  
  146.  
  147. void pw(winding_t *w)
  148. {
  149.     int        i;
  150.     for (i=0 ; i<w->numpoints ; i++)
  151.         printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
  152. }
  153.  
  154. void prl(leaf_t *l)
  155. {
  156.     int            i;
  157.     portal_t    *p;
  158.     plane_t        pl;
  159.     
  160.     for (i=0 ; i<l->numportals ; i++)
  161.     {
  162.         p = l->portals[i];
  163.         pl = p->plane;
  164.         printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
  165.     }
  166. }
  167.  
  168. /*
  169. ==================
  170. CopyWinding
  171. ==================
  172. */
  173. winding_t    *CopyWinding (winding_t *w)
  174. {
  175.     int            size;
  176.     winding_t    *c;
  177.     
  178.     size = (int)((winding_t *)0)->points[w->numpoints];
  179.     c = malloc (size);
  180.     memcpy (c, w, size);
  181.     c->original = false;
  182.     return c;
  183. }
  184.  
  185.  
  186. /*
  187. ==================
  188. ClipWinding
  189.  
  190. Clips the winding to the plane, returning the new winding on the positive side
  191. Frees the input winding.
  192. If keepon is true, an exactly on-plane winding will be saved, otherwise
  193. it will be clipped away.
  194. ==================
  195. */
  196. winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon)
  197. {
  198.     double    dists[MAX_POINTS_ON_WINDING];
  199.     int        sides[MAX_POINTS_ON_WINDING];
  200.     int        counts[3];
  201.     double    dot;
  202.     int        i, j;
  203.     double    *p1, *p2;
  204.     vec3_t    mid;
  205.     winding_t    *neww;
  206.     int        maxpts;
  207.     
  208.     counts[0] = counts[1] = counts[2] = 0;
  209.  
  210. /* determine sides for each point */
  211.     for (i=0 ; i<in->numpoints ; i++)
  212.     {
  213.         dot = DotProduct (in->points[i], split->normal);
  214.         dot -= split->dist;
  215.         dists[i] = dot;
  216.         if (dot > ON_EPSILON)
  217.             sides[i] = SIDE_FRONT;
  218.         else if (dot < -ON_EPSILON)
  219.             sides[i] = SIDE_BACK;
  220.         else
  221.         {
  222.             sides[i] = SIDE_ON;
  223.         }
  224.         counts[sides[i]]++;
  225.     }
  226.     sides[i] = sides[0];
  227.     dists[i] = dists[0];
  228.     
  229.     if (keepon && !counts[0] && !counts[1])
  230.         return in;
  231.         
  232.     if (!counts[0])
  233.     {
  234.         FreeWinding (in);
  235.         return NULL;
  236.     }
  237.     if (!counts[1])
  238.         return in;
  239.     
  240.     maxpts = in->numpoints+4;    /* can't use counts[0]+2 because */
  241.                                 /* of fp grouping errors */
  242.     neww = NewWinding (maxpts);
  243.         
  244.     for (i=0 ; i<in->numpoints ; i++)
  245.     {
  246.         p1 = in->points[i];
  247.         
  248.         if (sides[i] == SIDE_ON)
  249.         {
  250.             VectorCopy (p1, neww->points[neww->numpoints]);
  251.             neww->numpoints++;
  252.             continue;
  253.         }
  254.     
  255.         if (sides[i] == SIDE_FRONT)
  256.         {
  257.             VectorCopy (p1, neww->points[neww->numpoints]);
  258.             neww->numpoints++;
  259.         }
  260.         
  261.         if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  262.             continue;
  263.             
  264.     /* generate a split point */
  265.         p2 = in->points[(i+1)%in->numpoints];
  266.         
  267.         dot = dists[i] / (dists[i]-dists[i+1]);
  268.         for (j=0 ; j<3 ; j++)
  269.         {    /* avoid round off error when possible */
  270.             if (split->normal[j] == 1)
  271.                 mid[j] = split->dist;
  272.             else if (split->normal[j] == -1)
  273.                 mid[j] = -split->dist;
  274.             else
  275.                 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  276.         }
  277.             
  278.         VectorCopy (mid, neww->points[neww->numpoints]);
  279.         neww->numpoints++;
  280.     }
  281.     
  282.     if (neww->numpoints > maxpts)
  283.         Error ("ClipWinding: points exceeded estimate");
  284.         
  285. /* free the original winding */
  286.     FreeWinding (in);
  287.     
  288.     return neww;
  289. }
  290.  
  291.  
  292. /*============================================================================= */
  293.  
  294. /*
  295. =============
  296. GetNextPortal
  297.  
  298. Returns the next portal for a thread to work on
  299. Returns the portals from the least complex, so the later ones can reuse
  300. the earlier information.
  301. =============
  302. */
  303. portal_t *GetNextPortal (void)
  304. {
  305.     int        j;
  306.     portal_t    *p, *tp;
  307.     int        min;
  308.     
  309.     LOCK;
  310.  
  311.     min = 99999;
  312.     p = NULL;
  313.     
  314.     for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
  315.     {
  316.         if (tp->nummightsee < min && tp->status == stat_none)
  317.         {
  318.             min = tp->nummightsee;
  319.             p = tp;
  320.         }
  321.     }
  322.  
  323.     
  324.     if (p)
  325.         p->status = stat_working;
  326.  
  327.     UNLOCK;
  328.  
  329.     return p;
  330. }
  331.  
  332. /*
  333. ==============
  334. LeafThread
  335. ==============
  336. */
  337. #ifdef __alpha
  338. pthread_addr_t LeafThread (pthread_addr_t thread)
  339. #else
  340. void *LeafThread (int thread)
  341. #endif
  342. {
  343.     portal_t    *p;
  344.         int i = 1, j;
  345.         
  346.     ShowTempEntry ("Beginning leaf thread #%i\n", (int)thread);
  347.  
  348.     MoveCurs(4, 17);
  349.     CPrintf("$b4$f6"
  350.         "$f3-----------------------------" "$n"
  351.         "  $f6Portal $f2    0$f6 of $f2    0$f6  " "$n"
  352.         "    Portal number:    $f2    0$f6  " "$n"
  353.         "    Portal might see: $f2    0$f6  " "$n"
  354.         "    Portal can see:   $f2    0$f6  ");
  355.  
  356.     MoveCurs(23, 18);
  357.     CPrintf("$f2%5i", numportals*2);
  358.  
  359.         do
  360.     {
  361.         p = GetNextPortal ();
  362.         if (!p)
  363.             break;
  364.             
  365.         PortalFlow (p);
  366.  
  367.         MajorPercentBar(i*128/numportals);
  368.         SetForeColor(ANSI_GREEN);
  369.         SetBackColor(ANSI_BLUE);
  370.         MoveCurs(13, 18);
  371.         CPrintf("%5i", i++);
  372.         MoveCurs(26, 19);
  373.         CPrintf("%5i$n%5i$n%5i",
  374.             (int)(p - portals),
  375.             p->nummightsee, p->numcansee);
  376.  
  377.         } while (1);
  378.  
  379.     MoveCurs(4, 17);
  380.     CPrintf("$b4$f6"
  381.         "                             $n"
  382.         "                             $n"
  383.         "                             $n"
  384.         "                             $n"
  385.         "                             ");
  386.  
  387.     ShowTempEntry ("Completed leaf thread #%i\n", (int)thread);
  388.  
  389.     return NULL;
  390. }
  391.  
  392. /*
  393. ===============
  394. CompressRow
  395.  
  396. ===============
  397. */
  398. int CompressRow (byte *vis, byte *dest)
  399. {
  400.     int        j;
  401.     int        rep;
  402.     int        visrow;
  403.     byte    *dest_p;
  404.     
  405.     dest_p = dest;
  406.     visrow = (portalleafs + 7)>>3;
  407.     
  408.     for (j=0 ; j<visrow ; j++)
  409.     {
  410.         *dest_p++ = vis[j];
  411.         if (vis[j])
  412.             continue;
  413.  
  414.         rep = 1;
  415.         for ( j++; j<visrow ; j++)
  416.             if (vis[j] || rep == 255)
  417.                 break;
  418.             else
  419.                 rep++;
  420.         *dest_p++ = rep;
  421.         j--;
  422.     }
  423.     
  424.     return dest_p - dest;
  425. }
  426.  
  427.  
  428. /*
  429. ===============
  430. LeafFlow
  431.  
  432. Builds the entire visibility list for a leaf
  433. ===============
  434. */
  435. int        totalvis;
  436.  
  437. void LeafFlow (int leafnum)
  438. {
  439.     leaf_t        *leaf;
  440.     byte        *outbuffer;
  441.     byte        compressed[MAX_MAP_LEAFS/8];
  442.     int            i, j;
  443.     int            numvis;
  444.     byte        *dest;
  445.     portal_t    *p;
  446.     
  447. /* */
  448. /* flow through all portals, collecting visible bits */
  449. /* */
  450.     outbuffer = uncompressed + leafnum*bitbytes;
  451.     leaf = &leafs[leafnum];
  452.     for (i=0 ; i<leaf->numportals ; i++)
  453.     {
  454.         p = leaf->portals[i];
  455.         if (p->status != stat_done)
  456.             Error ("portal not done");
  457.         for (j=0 ; j<bitbytes ; j++)
  458.             outbuffer[j] |= p->visbits[j];
  459.     }
  460.  
  461.     if (outbuffer[leafnum>>3] & (1<<(leafnum&7)))
  462.         Error ("Leaf portals saw into leaf");
  463.         
  464.     outbuffer[leafnum>>3] |= (1<<(leafnum&7));
  465.  
  466.     numvis = 0;
  467.     for (i=0 ; i<portalleafs ; i++)
  468.         if (outbuffer[i>>3] & (1<<(i&3)))
  469.             numvis++;
  470.             
  471. /* */
  472. /* compress the bit string */
  473. /* */
  474.  
  475.         totalvis += numvis;
  476.  
  477. #if 0    
  478.     i = (portalleafs+7)>>3;
  479.     memcpy (compressed, outbuffer, i);
  480. #else
  481.     i = CompressRow (outbuffer, compressed);
  482. #endif
  483.  
  484.     dest = vismap_p;
  485.     vismap_p += i;
  486.     
  487.     if (vismap_p > vismap_end)
  488.         Error ("Vismap expansion overflow");
  489.  
  490.     dleafs[leafnum+1].visofs = dest-vismap;    /* leaf 0 is a common solid */
  491.  
  492.     memcpy (dest, compressed, i);    
  493. }
  494.  
  495.  
  496. /*
  497. ==================
  498. CalcPortalVis
  499. ==================
  500. */
  501. void CalcPortalVis (void)
  502. {
  503.     int        i;
  504.  
  505. /* fastvis just uses mightsee for a very loose bound */
  506.     if (fastvis)
  507.     {
  508.         for (i=0 ; i<numportals*2 ; i++)
  509.         {
  510.             portals[i].visbits = portals[i].mightsee;
  511.             portals[i].status = stat_done;
  512.         }
  513.         return;
  514.     }
  515.     
  516.     leafon = 0;
  517.     
  518. #ifdef __alpha
  519. {
  520.     pthread_t    work_threads[MAX_THREADS];
  521.     pthread_addr_t    status;
  522.     pthread_attr_t    attrib;
  523.     pthread_mutexattr_t    mattrib;
  524.     int        i;
  525.     
  526.     my_mutex = malloc (sizeof(*my_mutex));
  527.     if (pthread_mutexattr_create (&mattrib) == -1)
  528.         Error ("pthread_mutex_attr_create failed");
  529.     if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
  530.         Error ("pthread_mutexattr_setkind_np failed");
  531.     if (pthread_mutex_init (my_mutex, mattrib) == -1)
  532.         Error ("pthread_mutex_init failed");
  533.  
  534.     if (pthread_attr_create (&attrib) == -1)
  535.         Error ("pthread_attr_create failed");
  536.     if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
  537.         Error ("pthread_attr_setstacksize failed");
  538.     
  539.     for (i=0 ; i<numthreads ; i++)
  540.     {
  541.           if (pthread_create(&work_threads[i], attrib
  542.         , LeafThread, (pthread_addr_t)i) == -1)
  543.             Error ("pthread_create failed");
  544.     }
  545.         
  546.     for (i=0 ; i<numthreads ; i++)
  547.     {
  548.         if (pthread_join (work_threads[i], &status) == -1)
  549.             Error ("pthread_join failed");
  550.     }
  551.  
  552.     if (pthread_mutex_destroy (my_mutex) == -1)
  553.             Error ("pthread_mutex_destroy failed");
  554. }
  555. #else
  556.     LeafThread (0);
  557. #endif
  558.  
  559. }
  560.  
  561.  
  562. /*
  563. ==================
  564. CalcVis
  565. ==================
  566. */
  567. void CalcVis (void)
  568. {
  569.     int        i;
  570.  
  571.     ShowStatusEntry("Beginning basic portal vis.");
  572.     
  573.     BasePortalVis ();
  574.     
  575.     ShowStatusEntry("Beginning primary portal vis.");
  576.     
  577.     CalcPortalVis ();
  578.  
  579.     ShowStatusEntry("Assembling vis data into a table.");
  580.  
  581. /* */
  582. /* assemble the leaf vis lists by oring and compressing the portal lists */
  583. /* */
  584.     for (i=0 ; i<portalleafs ; i++) {
  585.         PercentBar(i*256/portalleafs);
  586.         LeafFlow (i);
  587.     }
  588.  
  589.     ShowTempEntry("Total leaves:          %5i\n", portalleafs);
  590.     ShowTempEntry("Total visible leaves:  %5i\n", totalvis);
  591.     ShowTempEntry("Average leaves visible:%5i\n", totalvis/portalleafs);
  592. }
  593.  
  594. /*
  595. ==============================================================================
  596.  
  597. PASSAGE CALCULATION (not used yet...)
  598.  
  599. ==============================================================================
  600. */
  601.  
  602. int        count_sep;
  603.  
  604. qboolean PlaneCompare (plane_t *p1, plane_t *p2)
  605. {
  606.     int        i;
  607.  
  608.     if ( fabs(p1->dist - p2->dist) > 0.01)
  609.         return false;
  610.  
  611.     for (i=0 ; i<3 ; i++)
  612.         if ( fabs(p1->normal[i] - p2->normal[i] ) > 0.001)
  613.             return false;
  614.  
  615.     return true;                
  616. }
  617.  
  618. sep_t    *Findpassages (winding_t *source, winding_t *pass)
  619. {
  620.     int            i, j, k, l;
  621.     plane_t        plane;
  622.     vec3_t        v1, v2;
  623.     float        d;
  624.     double        length;
  625.     int            counts[3];
  626.     qboolean        fliptest;
  627.     sep_t        *sep, *list;
  628.     
  629.     list = NULL;
  630.  
  631. /* check all combinations     */
  632.     for (i=0 ; i<source->numpoints ; i++)
  633.     {
  634.         l = (i+1)%source->numpoints;
  635.         VectorSubtract (source->points[l] , source->points[i], v1);
  636.  
  637.     /* fing a vertex of pass that makes a plane that puts all of the */
  638.     /* vertexes of pass on the front side and all of the vertexes of */
  639.     /* source on the back side */
  640.         for (j=0 ; j<pass->numpoints ; j++)
  641.         {
  642.             VectorSubtract (pass->points[j], source->points[i], v2);
  643.  
  644.             plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
  645.             plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
  646.             plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
  647.             
  648.         /* if points don't make a valid plane, skip it */
  649.  
  650.             length = plane.normal[0] * plane.normal[0]
  651.             + plane.normal[1] * plane.normal[1]
  652.             + plane.normal[2] * plane.normal[2];
  653.             
  654.             if (length < ON_EPSILON)
  655.                 continue;
  656.  
  657.             length = 1/sqrt(length);
  658.             
  659.             plane.normal[0] *= length;
  660.             plane.normal[1] *= length;
  661.             plane.normal[2] *= length;
  662.  
  663.             plane.dist = DotProduct (pass->points[j], plane.normal);
  664.  
  665.         /* */
  666.         /* find out which side of the generated seperating plane has the */
  667.         /* source portal */
  668.         /* */
  669.             fliptest = false;
  670.             for (k=0 ; k<source->numpoints ; k++)
  671.             {
  672.                 if (k == i || k == l)
  673.                     continue;
  674.                 d = DotProduct (source->points[k], plane.normal) - plane.dist;
  675.                 if (d < -ON_EPSILON)
  676.                 {    /* source is on the negative side, so we want all */
  677.                     /* pass and target on the positive side */
  678.                     fliptest = false;
  679.                     break;
  680.                 }
  681.                 else if (d > ON_EPSILON)
  682.                 {    /* source is on the positive side, so we want all */
  683.                     /* pass and target on the negative side */
  684.                     fliptest = true;
  685.                     break;
  686.                 }
  687.             }
  688.             if (k == source->numpoints)
  689.                 continue;        /* planar with source portal */
  690.  
  691.         /* */
  692.         /* flip the normal if the source portal is backwards */
  693.         /* */
  694.             if (fliptest)
  695.             {
  696.                 VectorSubtract (vec3_origin, plane.normal, plane.normal);
  697.                 plane.dist = -plane.dist;
  698.             }
  699.             
  700.         /* */
  701.         /* if all of the pass portal points are now on the positive side, */
  702.         /* this is the seperating plane */
  703.         /* */
  704.             counts[0] = counts[1] = counts[2] = 0;
  705.             for (k=0 ; k<pass->numpoints ; k++)
  706.             {
  707.                 if (k==j)
  708.                     continue;
  709.                 d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  710.                 if (d < -ON_EPSILON)
  711.                     break;
  712.                 else if (d > ON_EPSILON)
  713.                     counts[0]++;
  714.                 else
  715.                     counts[2]++;
  716.             }
  717.             if (k != pass->numpoints)
  718.                 continue;    /* points on negative side, not a seperating plane */
  719.                 
  720.             if (!counts[0])
  721.                 continue;    /* planar with pass portal */
  722.         
  723.         /* */
  724.         /* save this out */
  725.         /* */
  726.             count_sep++;
  727.  
  728.             sep = malloc(sizeof(*sep));
  729.             sep->next = list;
  730.             list = sep;
  731.             sep->plane = plane;
  732.         }
  733.     }
  734.     
  735.     return list;
  736. }
  737.  
  738.  
  739.  
  740. /*
  741. ============
  742. CalcPassages
  743. ============
  744. */
  745. void CalcPassages (void)
  746. {
  747.     int        i, j, k;
  748.     int        count, count2;
  749.     leaf_t    *l;
  750.     portal_t    *p1, *p2;
  751.     sep_t        *sep;
  752.     passage_t        *passages;
  753.  
  754.     printf ("building passages...\n");
  755.  
  756.     count = count2 = 0;
  757.     for (i=0 ; i<portalleafs ; i++)
  758.     {
  759.         l = &leafs[i];
  760.  
  761.         for (j=0 ; j<l->numportals ; j++)
  762.         {
  763.             p1 = l->portals[j];
  764.             for (k=0 ; k<l->numportals ; k++)
  765.             {
  766.                 if (k==j)
  767.                     continue;
  768.                     
  769.                 count++;
  770.                 p2 = l->portals[k];
  771.             
  772.             /* definately can't see into a coplanar portal */
  773.                 if (PlaneCompare (&p1->plane, &p2->plane) )
  774.                     continue;
  775.                     
  776.                 count2++;
  777.  
  778.                 sep = Findpassages (p1->winding, p2->winding);
  779.                 if (!sep)
  780.                 {
  781. /*                    Error ("No seperating planes found in portal pair"); */
  782.                     count_sep++;
  783.                     sep = malloc(sizeof(*sep));
  784.                     sep->next = NULL;
  785.                     sep->plane = p1->plane;
  786.                 }
  787.                 passages = malloc(sizeof(*passages));
  788.                 passages->planes = sep;
  789.                 passages->from = p1->leaf;
  790.                 passages->to = p2->leaf;
  791.                 passages->next = l->passages;
  792.                 l->passages = passages;
  793.             }
  794.         }
  795.     }
  796.  
  797.     printf ("numpassages: %i (%i)\n", count2, count);
  798.     printf ("total passages: %i\n", count_sep);
  799. }
  800.  
  801. /*============================================================================= */
  802.  
  803. /*
  804. ============
  805. LoadPortals
  806. ============
  807. */
  808. void LoadPortals (char *name)
  809. {
  810.     int            i, j;
  811.     portal_t    *p;
  812.     leaf_t        *l;
  813.     char        magic[80];
  814.     FILE        *f;
  815.     int            numpoints;
  816.     winding_t    *w;
  817.     int            leafnums[2];
  818.     plane_t        plane;
  819.  
  820.     ShowStatusEntry("Loading portal file.");
  821.         
  822.     if (!strcmp(name,"-"))
  823.         f = stdin;
  824.     else
  825.     {
  826.         f = fopen(name, "r");
  827.         if (!f)
  828.         {
  829.                         printf ("LoadPortals: couldn't read %s\n",name);
  830.             printf ("No vising performed.\n");
  831.             exit (1);
  832.         }
  833.     }
  834.  
  835.     if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalleafs, &numportals) != 3)
  836.         Error ("LoadPortals: failed to read header");
  837.     if (strcmp(magic,PORTALFILE))
  838.         Error ("LoadPortals: not a portal file");
  839.  
  840.     ShowTempEntry("%4i portal leaves", portalleafs);
  841.     ShowTempEntry("%4i numportals", numportals);
  842.  
  843.     bitbytes = ((portalleafs+63)&~63)>>3;
  844.     bitlongs = bitbytes/sizeof(long);
  845.     
  846. /* each file portal is split into two memory portals */
  847.     portals = malloc(2*numportals*sizeof(portal_t));
  848.     memset (portals, 0, 2*numportals*sizeof(portal_t));
  849.     
  850.     leafs = malloc(portalleafs*sizeof(leaf_t));
  851.     memset (leafs, 0, portalleafs*sizeof(leaf_t));
  852.  
  853.     originalvismapsize = portalleafs*((portalleafs+7)/8);
  854.  
  855.     vismap = vismap_p = dvisdata;
  856.     vismap_end = vismap + MAX_MAP_VISIBILITY;
  857.         
  858.     for (i=0, p=portals ; i<numportals ; i++)
  859.     {
  860.         if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
  861.             != 3)
  862.             Error ("LoadPortals: reading portal %i", i);
  863.         if (numpoints > MAX_POINTS_ON_WINDING)
  864.             Error ("LoadPortals: portal %i has too many points", i);
  865.         if ( (unsigned)leafnums[0] > portalleafs
  866.         || (unsigned)leafnums[1] > portalleafs)
  867.             Error ("LoadPortals: reading portal %i", i);
  868.         
  869.         w = p->winding = NewWinding (numpoints);
  870.         w->original = true;
  871.         w->numpoints = numpoints;
  872.         
  873.         for (j=0 ; j<numpoints ; j++)
  874.         {
  875.             if (fscanf (f, "(%lf %lf %lf ) "
  876.             , &w->points[j][0], &w->points[j][1], &w->points[j][2]) != 3)
  877.                 Error ("LoadPortals: reading portal %i", i);
  878.         }
  879.         fscanf (f, "\n");
  880.         
  881.     /* calc plane */
  882.         PlaneFromWinding (w, &plane);
  883.  
  884.     /* create forward portal */
  885.         l = &leafs[leafnums[0]];
  886.         if (l->numportals == MAX_PORTALS_ON_LEAF)
  887.             Error ("Leaf with too many portals");
  888.         l->portals[l->numportals] = p;
  889.         l->numportals++;
  890.         
  891.         p->winding = w;
  892.         VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
  893.         p->plane.dist = -plane.dist;
  894.         p->leaf = leafnums[1];
  895.         p++;
  896.         
  897.     /* create backwards portal */
  898.         l = &leafs[leafnums[1]];
  899.         if (l->numportals == MAX_PORTALS_ON_LEAF)
  900.             Error ("Leaf with too many portals");
  901.         l->portals[l->numportals] = p;
  902.         l->numportals++;
  903.         
  904.         p->winding = w;
  905.         p->plane = plane;
  906.         p->leaf = leafnums[0];
  907.         p++;
  908.  
  909.     }
  910.     
  911.     fclose (f);
  912. }
  913.  
  914.  
  915. /*
  916. ===========
  917. main
  918. ===========
  919. */
  920. int main (int argc, char **argv)
  921. {
  922.     char        portalfile[1024];
  923.     char        source[1024];
  924.     char        log[1024];
  925.     int        i;
  926.     long int    diff;
  927.  
  928.         LogFile = NULL;
  929.  
  930.         for (i=1 ; i<argc ; i++)
  931.     {
  932. #if 0
  933.                 if (!strcmp(argv[i],"-threads"))
  934.         {
  935.             numthreads = atoi (argv[i+1]);
  936.             i++;
  937.         }
  938. #endif
  939.         if (!strcmp(argv[i], "-fast"))
  940.         {
  941.             printf ("fastvis = true\n");
  942.             fastvis = true;
  943.         }
  944.         else if (!strcmp(argv[i], "-level"))
  945.         {
  946.             testlevel = atoi(argv[i+1]);
  947.             printf ("testlevel = %i\n", testlevel);
  948.             i++;
  949.         }
  950. #if 0
  951.                 else if (!strcmp(argv[i], "-v"))
  952.         {
  953.             printf ("verbose = true\n");
  954.             verbose = true;
  955.         }
  956. #endif
  957.                 else if (argv[i][0] == '-')
  958.             Error ("Unknown option \"%s\"", argv[i]);
  959.         else
  960.             break;
  961.     }
  962.  
  963.         if (i != argc - 1) {
  964.         fprintf(stderr, "Usage:   vis [-fast] [-level #] bspfile\n"
  965.                 "\n"
  966.                 "   -fast     Use faster calculations with less accurate results\n"
  967.                 "   -level    Change testing level to # (1-4)\n");
  968.                 exit(-1);
  969.         }
  970.  
  971.         strcpy (source, argv[i]);
  972.     DefaultExtension (source, ".bsp");
  973.  
  974.     ScrnInit();
  975.     MoveCurs(2, 1);
  976.     CPrintf("$b4$f7Vis$f4 - $f2%s", source);
  977.  
  978.         strcpy(log, source);
  979.     StripExtension(log);
  980.     DefaultExtension (log, ".log");
  981.  
  982.     LogFile = fopen(log, "at");
  983.     fprintf(LogFile, "\n-------------------------------------------\n"
  984.              "*** BEGIN VIS ***\n\n");
  985.  
  986.     ShowStatusEntry("Loading BSP file.");
  987.  
  988.         LoadBSPFile (source);
  989.     
  990.     strcpy (portalfile, argv[i]);
  991.     StripExtension (portalfile);
  992.     strcat (portalfile, ".prt");
  993.         
  994.     LoadPortals (portalfile);
  995.     
  996.     uncompressed = malloc(bitbytes*portalleafs);
  997.     memset (uncompressed, 0, bitbytes*portalleafs);
  998.     
  999. /*    CalcPassages (); */
  1000.  
  1001.     CalcVis ();
  1002.  
  1003.     visdatasize = vismap_p - dvisdata;    
  1004.     ShowTempEntry("c_chains:        %5d", c_chains);
  1005.         ShowTempEntry("Vis data size:   %5d", visdatasize);
  1006.     ShowTempEntry("Compressed from: %5d", originalvismapsize);
  1007.  
  1008.     ShowStatusEntry("Calculating ambient sounds.");
  1009.     CalcAmbientSounds ();
  1010.  
  1011.     ShowStatusEntry("Writing BSP file.");
  1012.  
  1013.         WriteBSPFile (source);  
  1014.     
  1015. /*    unlink (portalfile); */
  1016.  
  1017.     diff = LastCheck - StartTime;
  1018.     fprintf(LogFile, "\nVis completed successfully.  Elapsed time: %02d:%02d:%02d\n",
  1019.         diff / 360, (diff / 60) % 59, diff % 59);
  1020.     fprintf(LogFile, "-------------------------------------------\n\n");
  1021.         fclose(LogFile);
  1022.     LogFile = NULL;
  1023.  
  1024.         InitText();
  1025.     printf("Vis completed successfully.  Elapsed time: %02d:%02d:%02d\n",
  1026.         diff / 360, (diff / 60) % 59, diff % 59);
  1027.  
  1028.     return 0;
  1029. }
  1030.  
  1031.